#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
打包脚本 - 将iOS崩溃堆栈解析工具打包为macOS应用程序
专为Apple Silicon (M系列芯片) 优化
"""

import os
import sys
import shutil
import subprocess
from setuptools import setup

def clean_build_dirs():
    """清理构建目录"""
    print("清理旧的构建目录...")
    dirs_to_clean = ['build', 'dist']
    for dir_name in dirs_to_clean:
        if os.path.exists(dir_name):
            shutil.rmtree(dir_name)
    
    # 清理.pyc文件
    for root, dirs, files in os.walk('.'):
        for file in files:
            if file.endswith('.pyc'):
                os.remove(os.path.join(root, file))
    
    print("清理完成")

def check_requirements():
    """检查打包环境要求"""
    print("检查打包环境...")
    
    # 检查是否为M系列芯片
    try:
        arch = subprocess.check_output(['uname', '-m']).decode('utf-8').strip()
        if arch != 'arm64':
            print(f"警告: 当前系统架构为 {arch}，不是 arm64 (Apple Silicon)")
            response = input("是否继续? (y/n): ")
            if response.lower() != 'y':
                print("已取消打包")
                sys.exit(1)
    except Exception as e:
        print(f"无法检测系统架构: {str(e)}")
    
    # 检查py2app是否已安装
    try:
        import py2app
        print(f"检测到py2app版本: {py2app.__version__}")
    except ImportError:
        print("未安装py2app，正在安装...")
        subprocess.call([sys.executable, '-m', 'pip', 'install', 'py2app'])
    
    # 检查PyQt6是否已安装
    try:
        import PyQt6
        print(f"检测到PyQt6")
    except ImportError:
        print("错误: 未安装PyQt6，请先安装所有依赖")
        print("运行: pip install -r requirements.txt")
        sys.exit(1)
    
    print("环境检查完成")

def build_app():
    """构建macOS应用程序"""
    print("开始构建应用程序...")
    
    # 设置py2app选项
    APP = ['main.py']
    DATA_FILES = ['README.md']
    
    OPTIONS = {
        'argv_emulation': False,
        'strip': True,
        'iconfile': 'app_icon.icns',  # 如果有图标文件，请提供路径
        'plist': {
            'CFBundleName': 'iOS崩溃堆栈解析工具',
            'CFBundleDisplayName': 'iOS崩溃堆栈解析工具',
            'CFBundleIdentifier': 'com.example.symbolicator',
            'CFBundleVersion': '1.0.0',
            'CFBundlePackageType': 'APPL',
            'CFBundleSignature': '????',
            'LSMinimumSystemVersion': '11.0',  # Big Sur或更高版本
            'NSHumanReadableCopyright': 'Copyright © 2023',
            'NSHighResolutionCapable': True,
        },
        'packages': [
            'PyQt6', 
            'pandas', 
            'chardet',
            'numpy',  # pandas依赖
        ],
        'includes': [
            'sip',
            'PyQt6.QtCore',
            'PyQt6.QtWidgets',
            'PyQt6.QtGui',
        ],
        'excludes': [
            'tkinter',
            'matplotlib',
            'scipy',
            'PyQt5',
            'PySide6',
            'PySide2',
            'wx',
        ],
        'resources': [
            # 如有其他资源，在此添加
        ],
        'optimize': 2,  # 优化字节码
        'arch': 'arm64',  # 指定为ARM64架构
    }
    
    # 确保工作目录正确
    original_dir = os.getcwd()
    
    try:
        # 设置命令行参数
        sys.argv = [sys.argv[0], 'py2app', '--no-chdir']
        
        # 增加递归深度限制
        sys.setrecursionlimit(1500)
        
        # 执行setup
        setup(
            name='iOS崩溃堆栈解析工具',
            app=APP,
            data_files=DATA_FILES,
            options={'py2app': OPTIONS},
            setup_requires=['py2app'],
        )
        
        print("应用程序构建完成!")
    
    except Exception as e:
        print(f"构建过程中出错: {str(e)}")
        return False
    
    finally:
        # 恢复工作目录
        os.chdir(original_dir)
    
    return True

def post_process():
    """打包后处理"""
    print("执行后处理...")
    
    app_path = os.path.join('dist', 'iOS崩溃堆栈解析工具.app')
    
    if not os.path.exists(app_path):
        print(f"错误: 应用程序不存在于 {app_path}")
        return False
    
    # 检查应用是否可运行
    print("验证应用程序...")
    try:
        # 获取Info.plist内容
        info_plist_path = os.path.join(app_path, 'Contents', 'Info.plist')
        subprocess.run(['plutil', '-p', info_plist_path], check=True)
        print("应用程序有效")
    except subprocess.CalledProcessError:
        print("警告: 无法验证应用程序有效性")
    
    # 创建DMG文件（可选）
    create_dmg = input("是否创建DMG安装镜像? (y/n): ")
    if create_dmg.lower() == 'y':
        try:
            dmg_name = 'iOS崩溃堆栈解析工具.dmg'
            if os.path.exists(dmg_name):
                os.remove(dmg_name)
            
            print("创建DMG文件...")
            subprocess.run([
                'hdiutil', 'create', '-volname', 'iOS崩溃堆栈解析工具',
                '-srcfolder', app_path, '-ov', '-format', 'UDZO', dmg_name
            ], check=True)
            print(f"DMG文件已创建: {dmg_name}")
        except subprocess.CalledProcessError as e:
            print(f"创建DMG文件时出错: {str(e)}")
    
    print("后处理完成")
    return True

def main():
    """主函数"""
    print("=" * 60)
    print("iOS崩溃堆栈解析工具打包脚本 (针对Apple Silicon优化)")
    print("=" * 60)
    
    # 检查是否有图标文件，如果没有则提示
    if not os.path.exists('app_icon.icns'):
        print("注意: 未找到图标文件 'app_icon.icns'，将使用默认图标")
    
    # 检查环境
    check_requirements()
    
    # 询问是否清理旧构建
    clean = input("是否清理旧的构建文件? (y/n): ")
    if clean.lower() == 'y':
        clean_build_dirs()
    
    # 构建应用
    if build_app():
        post_process()
        
        # 完成提示
        print("\n" + "=" * 60)
        print("打包完成!")
        print(f"应用程序位置: {os.path.abspath('dist/iOS崩溃堆栈解析工具.app')}")
        print("=" * 60)
    else:
        print("\n打包失败!")

if __name__ == "__main__":
    main()
